const fs = require('fs');
const path = require('path');

/**
 * 全面深度学习 OHCode 目录下所有项目
 * 
 * 学习内容：
 * 1. 所有源代码文件（.cpp/.h）的实际实现
 * 2. 所有测试文件（_test.cpp/_unittest.cpp）的测试模式
 * 3. 所有 Fuzz 文件（_fuzzer.cpp）的 fuzz 模式
 * 4. 所有 BUILD.gn 的配置（deps、external_deps、include_dirs）
 * 5. 常用的头文件、类、函数、宏
 * 6. 常见的编译配置和依赖关系
 * 
 * 目标：生成高质量的 Prompt，让 LLM 能生成可直接编译的测试代码
 */

const OHCODE_DIR = path.join(__dirname, '../OHCode');
const OUTPUT_FILE = path.join(__dirname, '../core/knowledge/comprehensive-all-projects.json');

// 统计信息
const stats = {
    totalProjects: 0,
    totalSourceFiles: 0,
    totalHeaderFiles: 0,
    totalTestFiles: 0,
    totalFuzzFiles: 0,
    totalBuildGnFiles: 0,
    startTime: Date.now()
};

// 知识库
const knowledge = {
    // 常用头文件（按使用频率排序）
    commonHeaders: new Map(),
    
    // 常用类（包含命名空间）
    commonClasses: new Map(),
    
    // 常用函数模式
    commonFunctions: new Map(),
    
    // 常用宏定义
    commonMacros: new Map(),
    
    // 测试模式（HWTEST_F、EXPECT_*）
    testPatterns: {
        hwtestExamples: [],
        mockExamples: [],
        assertionExamples: [],
        setupTeardownExamples: []
    },
    
    // Fuzz 模式
    fuzzPatterns: {
        llvmFuzzerExamples: [],
        messageParcelUsage: [],
        fuzzedDataProviderUsage: [],
        inputValidation: []
    },
    
    // GN 配置模式
    gnPatterns: {
        commonDeps: new Map(),
        commonExternalDeps: new Map(),
        commonIncludeDirs: new Map(),
        commonDefines: new Map()
    },
    
    // 真实的完整示例（用于 Prompt）
    realWorldExamples: {
        // 源代码 + 对应的测试代码
        sourceWithTests: [],
        // 源代码 + 对应的 Fuzz 代码
        sourceWithFuzz: [],
        // 复杂类的测试示例
        complexClassTests: [],
        // 接口类的测试示例
        interfaceTests: []
    }
};

/**
 * 递归扫描目录
 */
function scanDirectory(dir, callback) {
    if (!fs.existsSync(dir)) return;
    
    const entries = fs.readdirSync(dir, { withFileTypes: true });
    
    for (const entry of entries) {
        const fullPath = path.join(dir, entry.name);
        
        // 跳过 node_modules、.git 等
        if (entry.name.startsWith('.') || 
            entry.name === 'node_modules' || 
            entry.name === 'out' ||
            entry.name === 'build') {
            continue;
        }
        
        if (entry.isDirectory()) {
            scanDirectory(fullPath, callback);
        } else if (entry.isFile()) {
            callback(fullPath);
        }
    }
}

/**
 * 提取头文件 include
 */
function extractIncludes(content) {
    const includes = [];
    const regex = /#include\s+[<"]([^>"]+)[>"]/g;
    let match;
    while ((match = regex.exec(content)) !== null) {
        includes.push(match[1]);
    }
    return includes;
}

/**
 * 提取类名（包含命名空间）
 */
function extractClasses(content) {
    const classes = [];
    
    // 提取 class、struct
    const classRegex = /(?:namespace\s+(\w+)\s*\{)?\s*(?:class|struct)\s+(\w+)(?:\s*:\s*public\s+(\w+))?/g;
    let match;
    while ((match = classRegex.exec(content)) !== null) {
        const namespace = match[1] || '';
        const className = match[2];
        const baseClass = match[3] || '';
        
        classes.push({
            namespace,
            className,
            baseClass,
            fullName: namespace ? `${namespace}::${className}` : className
        });
    }
    
    return classes;
}

/**
 * 提取函数签名
 */
function extractFunctions(content) {
    const functions = [];
    
    // 匹配函数定义（简化版）
    const funcRegex = /(?:virtual\s+)?(\w+(?:::\w+)?)\s+(\w+)\s*\(([^)]*)\)/g;
    let match;
    while ((match = funcRegex.exec(content)) !== null) {
        functions.push({
            returnType: match[1],
            name: match[2],
            params: match[3].trim()
        });
    }
    
    return functions;
}

/**
 * 提取宏定义
 */
function extractMacros(content) {
    const macros = [];
    const regex = /#define\s+(\w+)(?:\(([^)]*)\))?\s+(.+)/g;
    let match;
    while ((match = regex.exec(content)) !== null) {
        macros.push({
            name: match[1],
            params: match[2] || '',
            value: match[3].trim()
        });
    }
    return macros;
}

/**
 * 分析源代码文件
 */
function analyzeSourceFile(filePath, content) {
    const includes = extractIncludes(content);
    includes.forEach(inc => {
        knowledge.commonHeaders.set(inc, (knowledge.commonHeaders.get(inc) || 0) + 1);
    });
    
    const classes = extractClasses(content);
    classes.forEach(cls => {
        knowledge.commonClasses.set(cls.fullName, (knowledge.commonClasses.get(cls.fullName) || 0) + 1);
    });
    
    const functions = extractFunctions(content);
    functions.forEach(func => {
        const key = `${func.returnType} ${func.name}`;
        knowledge.commonFunctions.set(key, (knowledge.commonFunctions.get(key) || 0) + 1);
    });
    
    const macros = extractMacros(content);
    macros.forEach(macro => {
        knowledge.commonMacros.set(macro.name, (knowledge.commonMacros.get(macro.name) || 0) + 1);
    });
}

/**
 * 分析测试文件
 */
function analyzeTestFile(filePath, content) {
    // 提取 HWTEST_F
    const hwtestRegex = /HWTEST_F\s*\(([^,]+),\s*([^,]+),\s*([^)]+)\)\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/gs;
    let match;
    while ((match = hwtestRegex.exec(content)) !== null) {
        knowledge.testPatterns.hwtestExamples.push({
            className: match[1].trim(),
            testName: match[2].trim(),
            level: match[3].trim(),
            body: match[4].trim().substring(0, 500) // 限制长度
        });
    }
    
    // 提取 Mock 用法
    if (content.includes('EXPECT_CALL') || content.includes('ON_CALL')) {
        const mockRegex = /((?:EXPECT_CALL|ON_CALL)\s*\([^;]+;)/g;
        while ((match = mockRegex.exec(content)) !== null) {
            knowledge.testPatterns.mockExamples.push(match[1].trim());
        }
    }
    
    // 提取断言
    const assertRegex = /(EXPECT_(?:EQ|NE|TRUE|FALSE|GT|LT|GE|LE|STREQ|STRNE)\s*\([^;]+;)/g;
    while ((match = assertRegex.exec(content)) !== null) {
        knowledge.testPatterns.assertionExamples.push(match[1].trim());
    }
    
    // 提取 SetUp/TearDown
    if (content.includes('SetUp()') || content.includes('TearDown()')) {
        const setupRegex = /(?:void\s+)?(?:SetUp|TearDown)\s*\(\s*\)\s*(?:override)?\s*\{([^}]+)\}/g;
        while ((match = setupRegex.exec(content)) !== null) {
            knowledge.testPatterns.setupTeardownExamples.push(match[0].trim());
        }
    }
}

/**
 * 分析 Fuzz 文件
 */
function analyzeFuzzFile(filePath, content) {
    // 提取 LLVMFuzzerTestOneInput
    const fuzzerRegex = /extern\s+"C"\s+int\s+LLVMFuzzerTestOneInput\s*\([^)]+\)\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/gs;
    let match;
    while ((match = fuzzerRegex.exec(content)) !== null) {
        knowledge.fuzzPatterns.llvmFuzzerExamples.push(match[0].substring(0, 800));
    }
    
    // 提取 MessageParcel 用法
    if (content.includes('MessageParcel')) {
        const parcelRegex = /(MessageParcel[^;]+;)/g;
        while ((match = parcelRegex.exec(content)) !== null) {
            knowledge.fuzzPatterns.messageParcelUsage.push(match[1].trim());
        }
    }
    
    // 提取 FuzzedDataProvider 用法
    if (content.includes('FuzzedDataProvider')) {
        const providerRegex = /(FuzzedDataProvider[^;]+;)/g;
        while ((match = providerRegex.exec(content)) !== null) {
            knowledge.fuzzPatterns.fuzzedDataProviderUsage.push(match[1].trim());
        }
    }
    
    // 提取输入验证模式
    const validationRegex = /if\s*\([^{]+(?:nullptr|size|length)[^{]+\)\s*\{[^}]*return[^}]*\}/g;
    while ((match = validationRegex.exec(content)) !== null) {
        knowledge.fuzzPatterns.inputValidation.push(match[0].trim());
    }
}

/**
 * 分析 BUILD.gn 文件
 */
function analyzeBuildGn(filePath, content) {
    // 提取 deps
    const depsRegex = /deps\s*=\s*\[([^\]]+)\]/gs;
    let match;
    while ((match = depsRegex.exec(content)) !== null) {
        const deps = match[1].split(',').map(d => d.trim().replace(/["']/g, ''));
        deps.forEach(dep => {
            if (dep && !dep.startsWith('#')) {
                knowledge.gnPatterns.commonDeps.set(dep, (knowledge.gnPatterns.commonDeps.get(dep) || 0) + 1);
            }
        });
    }
    
    // 提取 external_deps
    const externalDepsRegex = /external_deps\s*=\s*\[([^\]]+)\]/gs;
    while ((match = externalDepsRegex.exec(content)) !== null) {
        const deps = match[1].split(',').map(d => d.trim().replace(/["']/g, ''));
        deps.forEach(dep => {
            if (dep && !dep.startsWith('#')) {
                knowledge.gnPatterns.commonExternalDeps.set(dep, (knowledge.gnPatterns.commonExternalDeps.get(dep) || 0) + 1);
            }
        });
    }
    
    // 提取 include_dirs
    const includeDirsRegex = /include_dirs\s*=\s*\[([^\]]+)\]/gs;
    while ((match = includeDirsRegex.exec(content)) !== null) {
        const dirs = match[1].split(',').map(d => d.trim().replace(/["']/g, ''));
        dirs.forEach(dir => {
            if (dir && !dir.startsWith('#')) {
                knowledge.gnPatterns.commonIncludeDirs.set(dir, (knowledge.gnPatterns.commonIncludeDirs.get(dir) || 0) + 1);
            }
        });
    }
    
    // 提取 defines
    const definesRegex = /defines\s*=\s*\[([^\]]+)\]/gs;
    while ((match = definesRegex.exec(content)) !== null) {
        const defines = match[1].split(',').map(d => d.trim().replace(/["']/g, ''));
        defines.forEach(define => {
            if (define && !define.startsWith('#')) {
                knowledge.gnPatterns.commonDefines.set(define, (knowledge.gnPatterns.commonDefines.get(define) || 0) + 1);
            }
        });
    }
}

/**
 * 尝试关联源文件和测试文件
 */
function associateSourceWithTest(sourceFiles, testFiles, fuzzFiles) {
    console.log('\n📚 关联源文件与测试文件...');
    
    for (const sourceFile of sourceFiles) {
        const baseName = path.basename(sourceFile, path.extname(sourceFile));
        
        // 查找对应的测试文件
        const testFile = testFiles.find(tf => {
            const testBaseName = path.basename(tf).replace(/_test\.cpp|_unittest\.cpp/, '');
            return testBaseName === baseName;
        });
        
        if (testFile && fs.existsSync(sourceFile) && fs.existsSync(testFile)) {
            try {
                const sourceContent = fs.readFileSync(sourceFile, 'utf-8');
                const testContent = fs.readFileSync(testFile, 'utf-8');
                
                knowledge.realWorldExamples.sourceWithTests.push({
                    sourcePath: sourceFile,
                    testPath: testFile,
                    sourceSnippet: sourceContent.substring(0, 1000),
                    testSnippet: testContent.substring(0, 1000)
                });
            } catch (err) {
                // 跳过读取失败的文件
            }
        }
        
        // 查找对应的 Fuzz 文件
        const fuzzFile = fuzzFiles.find(ff => {
            const fuzzBaseName = path.basename(ff).replace(/_fuzzer\.cpp/, '').replace(/_/g, '');
            const sourceBaseName = baseName.replace(/_/g, '');
            return fuzzBaseName.includes(sourceBaseName) || sourceBaseName.includes(fuzzBaseName);
        });
        
        if (fuzzFile && fs.existsSync(sourceFile) && fs.existsSync(fuzzFile)) {
            try {
                const sourceContent = fs.readFileSync(sourceFile, 'utf-8');
                const fuzzContent = fs.readFileSync(fuzzFile, 'utf-8');
                
                knowledge.realWorldExamples.sourceWithFuzz.push({
                    sourcePath: sourceFile,
                    fuzzPath: fuzzFile,
                    sourceSnippet: sourceContent.substring(0, 1000),
                    fuzzSnippet: fuzzContent.substring(0, 1000)
                });
            } catch (err) {
                // 跳过读取失败的文件
            }
        }
    }
    
    console.log(`  ✅ 关联到 ${knowledge.realWorldExamples.sourceWithTests.length} 对源文件-测试文件`);
    console.log(`  ✅ 关联到 ${knowledge.realWorldExamples.sourceWithFuzz.length} 对源文件-Fuzz 文件`);
}

/**
 * 主函数
 */
async function main() {
    console.log('🚀 开始全面深度学习 OHCode 目录下所有项目...\n');
    console.log(`📂 扫描目录: ${OHCODE_DIR}\n`);
    
    if (!fs.existsSync(OHCODE_DIR)) {
        console.error(`❌ OHCode 目录不存在: ${OHCODE_DIR}`);
        process.exit(1);
    }
    
    // 第一遍：收集所有文件路径
    const allSourceFiles = [];
    const allHeaderFiles = [];
    const allTestFiles = [];
    const allFuzzFiles = [];
    const allBuildGnFiles = [];
    
    console.log('📋 第一步：收集所有文件路径...');
    
    const projects = fs.readdirSync(OHCODE_DIR, { withFileTypes: true })
        .filter(d => d.isDirectory())
        .map(d => d.name);
    
    stats.totalProjects = projects.length;
    console.log(`  发现 ${stats.totalProjects} 个项目\n`);
    
    for (const project of projects) {
        const projectPath = path.join(OHCODE_DIR, project);
        console.log(`  📁 扫描项目: ${project}`);
        
        scanDirectory(projectPath, (filePath) => {
            const ext = path.extname(filePath);
            const basename = path.basename(filePath);
            
            if (ext === '.cpp') {
                if (basename.includes('_test.cpp') || basename.includes('_unittest.cpp')) {
                    allTestFiles.push(filePath);
                } else if (basename.includes('_fuzzer.cpp')) {
                    allFuzzFiles.push(filePath);
                } else {
                    allSourceFiles.push(filePath);
                }
            } else if (ext === '.h' || ext === '.hpp') {
                allHeaderFiles.push(filePath);
            } else if (basename === 'BUILD.gn') {
                allBuildGnFiles.push(filePath);
            }
        });
    }
    
    stats.totalSourceFiles = allSourceFiles.length;
    stats.totalHeaderFiles = allHeaderFiles.length;
    stats.totalTestFiles = allTestFiles.length;
    stats.totalFuzzFiles = allFuzzFiles.length;
    stats.totalBuildGnFiles = allBuildGnFiles.length;
    
    console.log(`\n📊 文件统计:`);
    console.log(`  - 源文件 (.cpp): ${stats.totalSourceFiles}`);
    console.log(`  - 头文件 (.h/.hpp): ${stats.totalHeaderFiles}`);
    console.log(`  - 测试文件: ${stats.totalTestFiles}`);
    console.log(`  - Fuzz 文件: ${stats.totalFuzzFiles}`);
    console.log(`  - BUILD.gn 文件: ${stats.totalBuildGnFiles}`);
    
    // 第二遍：分析所有文件内容
    console.log(`\n📋 第二步：深度分析文件内容...\n`);
    
    let processedCount = 0;
    const totalFiles = allSourceFiles.length + allHeaderFiles.length + allTestFiles.length + allFuzzFiles.length + allBuildGnFiles.length;
    
    // 分析源文件和头文件
    console.log(`  📝 分析源文件和头文件...`);
    for (const filePath of [...allSourceFiles, ...allHeaderFiles]) {
        try {
            const content = fs.readFileSync(filePath, 'utf-8');
            analyzeSourceFile(filePath, content);
            processedCount++;
            
            if (processedCount % 100 === 0) {
                const percent = ((processedCount / totalFiles) * 100).toFixed(1);
                process.stdout.write(`\r  进度: ${processedCount}/${totalFiles} (${percent}%)`);
            }
        } catch (err) {
            // 跳过读取失败的文件
        }
    }
    
    // 分析测试文件
    console.log(`\n  🧪 分析测试文件...`);
    for (const filePath of allTestFiles) {
        try {
            const content = fs.readFileSync(filePath, 'utf-8');
            analyzeTestFile(filePath, content);
            processedCount++;
            
            if (processedCount % 100 === 0) {
                const percent = ((processedCount / totalFiles) * 100).toFixed(1);
                process.stdout.write(`\r  进度: ${processedCount}/${totalFiles} (${percent}%)`);
            }
        } catch (err) {
            // 跳过读取失败的文件
        }
    }
    
    // 分析 Fuzz 文件
    console.log(`\n  🐛 分析 Fuzz 文件...`);
    for (const filePath of allFuzzFiles) {
        try {
            const content = fs.readFileSync(filePath, 'utf-8');
            analyzeFuzzFile(filePath, content);
            processedCount++;
            
            if (processedCount % 100 === 0) {
                const percent = ((processedCount / totalFiles) * 100).toFixed(1);
                process.stdout.write(`\r  进度: ${processedCount}/${totalFiles} (${percent}%)`);
            }
        } catch (err) {
            // 跳过读取失败的文件
        }
    }
    
    // 分析 BUILD.gn 文件
    console.log(`\n  🔧 分析 BUILD.gn 文件...`);
    for (const filePath of allBuildGnFiles) {
        try {
            const content = fs.readFileSync(filePath, 'utf-8');
            analyzeBuildGn(filePath, content);
            processedCount++;
            
            if (processedCount % 100 === 0) {
                const percent = ((processedCount / totalFiles) * 100).toFixed(1);
                process.stdout.write(`\r  进度: ${processedCount}/${totalFiles} (${percent}%)`);
            }
        } catch (err) {
            // 跳过读取失败的文件
        }
    }
    
    console.log(`\n  ✅ 完成文件分析`);
    
    // 第三遍：关联源文件和测试文件
    associateSourceWithTest(allSourceFiles, allTestFiles, allFuzzFiles);
    
    // 转换 Map 为数组并排序
    console.log(`\n📊 第三步：整理和排序知识库...`);
    
    const sortedKnowledge = {
        // 按使用频率排序，取前 100
        commonHeaders: Array.from(knowledge.commonHeaders.entries())
            .sort((a, b) => b[1] - a[1])
            .slice(0, 100)
            .map(([header, count]) => ({ header, count })),
        
        commonClasses: Array.from(knowledge.commonClasses.entries())
            .sort((a, b) => b[1] - a[1])
            .slice(0, 200)
            .map(([className, count]) => ({ className, count })),
        
        commonFunctions: Array.from(knowledge.commonFunctions.entries())
            .sort((a, b) => b[1] - a[1])
            .slice(0, 200)
            .map(([signature, count]) => ({ signature, count })),
        
        commonMacros: Array.from(knowledge.commonMacros.entries())
            .sort((a, b) => b[1] - a[1])
            .slice(0, 100)
            .map(([macro, count]) => ({ macro, count })),
        
        testPatterns: {
            hwtestExamples: knowledge.testPatterns.hwtestExamples.slice(0, 50),
            mockExamples: knowledge.testPatterns.mockExamples.slice(0, 50),
            assertionExamples: knowledge.testPatterns.assertionExamples.slice(0, 50),
            setupTeardownExamples: knowledge.testPatterns.setupTeardownExamples.slice(0, 20)
        },
        
        fuzzPatterns: {
            llvmFuzzerExamples: knowledge.fuzzPatterns.llvmFuzzerExamples.slice(0, 30),
            messageParcelUsage: knowledge.fuzzPatterns.messageParcelUsage.slice(0, 30),
            fuzzedDataProviderUsage: knowledge.fuzzPatterns.fuzzedDataProviderUsage.slice(0, 30),
            inputValidation: knowledge.fuzzPatterns.inputValidation.slice(0, 30)
        },
        
        gnPatterns: {
            commonDeps: Array.from(knowledge.gnPatterns.commonDeps.entries())
                .sort((a, b) => b[1] - a[1])
                .slice(0, 100)
                .map(([dep, count]) => ({ dep, count })),
            
            commonExternalDeps: Array.from(knowledge.gnPatterns.commonExternalDeps.entries())
                .sort((a, b) => b[1] - a[1])
                .slice(0, 100)
                .map(([dep, count]) => ({ dep, count })),
            
            commonIncludeDirs: Array.from(knowledge.gnPatterns.commonIncludeDirs.entries())
                .sort((a, b) => b[1] - a[1])
                .slice(0, 100)
                .map(([dir, count]) => ({ dir, count })),
            
            commonDefines: Array.from(knowledge.gnPatterns.commonDefines.entries())
                .sort((a, b) => b[1] - a[1])
                .slice(0, 50)
                .map(([define, count]) => ({ define, count }))
        },
        
        realWorldExamples: {
            sourceWithTests: knowledge.realWorldExamples.sourceWithTests.slice(0, 20),
            sourceWithFuzz: knowledge.realWorldExamples.sourceWithFuzz.slice(0, 20),
            complexClassTests: knowledge.realWorldExamples.complexClassTests.slice(0, 10),
            interfaceTests: knowledge.realWorldExamples.interfaceTests.slice(0, 10)
        },
        
        stats,
        generatedAt: new Date().toISOString()
    };
    
    // 保存知识库
    const outputDir = path.dirname(OUTPUT_FILE);
    if (!fs.existsSync(outputDir)) {
        fs.mkdirSync(outputDir, { recursive: true });
    }
    
    fs.writeFileSync(OUTPUT_FILE, JSON.stringify(sortedKnowledge, null, 2), 'utf-8');
    
    const elapsed = ((Date.now() - stats.startTime) / 1000).toFixed(1);
    
    console.log(`\n✅ 深度学习完成！`);
    console.log(`\n📊 学习成果统计:`);
    console.log(`  - 常用头文件: ${sortedKnowledge.commonHeaders.length} 个`);
    console.log(`  - 常用类: ${sortedKnowledge.commonClasses.length} 个`);
    console.log(`  - 常用函数模式: ${sortedKnowledge.commonFunctions.length} 个`);
    console.log(`  - 常用宏: ${sortedKnowledge.commonMacros.length} 个`);
    console.log(`  - HWTEST_F 示例: ${sortedKnowledge.testPatterns.hwtestExamples.length} 个`);
    console.log(`  - Mock 示例: ${sortedKnowledge.testPatterns.mockExamples.length} 个`);
    console.log(`  - 断言示例: ${sortedKnowledge.testPatterns.assertionExamples.length} 个`);
    console.log(`  - LLVMFuzzer 示例: ${sortedKnowledge.fuzzPatterns.llvmFuzzerExamples.length} 个`);
    console.log(`  - 常用 deps: ${sortedKnowledge.gnPatterns.commonDeps.length} 个`);
    console.log(`  - 常用 external_deps: ${sortedKnowledge.gnPatterns.commonExternalDeps.length} 个`);
    console.log(`  - 源文件-测试文件对: ${sortedKnowledge.realWorldExamples.sourceWithTests.length} 对`);
    console.log(`  - 源文件-Fuzz 文件对: ${sortedKnowledge.realWorldExamples.sourceWithFuzz.length} 对`);
    console.log(`\n💾 知识库已保存到: ${OUTPUT_FILE}`);
    console.log(`⏱️  总耗时: ${elapsed} 秒`);
}

main().catch(err => {
    console.error('\n❌ 错误:', err);
    process.exit(1);
});

